#include "Task.hpp"
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

const int processnum = 10;
std::vector<task_t> tasks;

class channel
{
public:
    channel(int cmdfd, int slaverid, const std::string &processname)
    :_cmdfd(cmdfd)
    ,_slaverid(slaverid)
    ,_processname(processname)
    {}

    int _cmdfd;
    pid_t _slaverid;
    std::string _processname;
};

void slaver()
{
    while(true)
    {
        int cmdcode = 0;
        int n = read(0, &cmdcode, sizeof(int));
        if(n == sizeof(int))
        {
            std::cout << "slaver say@ get a command: " << getpid() << " : cmdcode: " << cmdcode << std::endl;
            if(cmdcode >= 0 && cmdcode < tasks.size()) 
            {
                tasks[cmdcode]();
            }
        }
        if(n == 0)
        {
            break;
        }
    }
}

// 输入：const &
// 输出：*
// 输入输出：&

void InitProcessPool(std::vector<channel> *channels)
{
    std::vector<int> oldfds;
    for(int i = 0; i < processnum; ++i)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if(n < 0)
        {
            exit(1);
        }

        pid_t id = fork();
        if(id < 0)
        {
            exit(2);
        }
        if(id == 0)
        {
            std::cout << "child: " << getpid() << " close history fd: ";
            for(auto fd : oldfds) 
            {
                std::cout << fd << " ";
                close(fd);
            }
            std::cout << std::endl;
            close(pipefd[1]);
            dup2(pipefd[0], 0);
            close(pipefd[0]);
            slaver();
            std::cout << "process : " << getpid() << " quit" << std::endl;
            exit(0);
        }
        close(pipefd[0]);

        std::string name = "process-" + std::to_string(i);
        channels->push_back(channel(pipefd[1], id, name));
        oldfds.push_back(pipefd[1]);
        
        sleep(1);
    }
}

void Menu()
{
    std::cout << "################################################" << std::endl;
    std::cout << "# 1. 刷新日志             2. 刷新出来野怪        #" << std::endl;
    std::cout << "# 3. 检测软件是否更新      4. 更新用的血量和蓝量  #" << std::endl;
    std::cout << "#                         0. 退出               #" << std::endl;
    std::cout << "#################################################" << std::endl;
}

void ctrlSlaver(const std::vector<channel> &channels)
{
    int which = 0;
    while(true)
    {
        int select = 0;
        Menu();
        std::cout << "Please Enter@";
        std::cin >> select;
        if(select <= 0 || select >= 5)
        {
            break;
        }
        int cmdcode = select - 1;
        std::cout << "father say: " << " cmdcode: " <<
        cmdcode << " already sendto " << channels[which]._slaverid << " process name: " 
        << channels[which]._processname << std::endl;
        write(channels[which]._cmdfd, &cmdcode, sizeof(cmdcode));
        which++;
        which %= channels.size();
        sleep(1);
    }
}

void QuitProcess(const std::vector<channel> &channels)
{
    for(const auto &c : channels)
    {
        close(c._cmdfd);
        waitpid(c._slaverid, nullptr, 0);
    }
}

int main()
{
    LoadTask(&tasks);

    std::vector<channel> channels;

    InitProcessPool(&channels);

    ctrlSlaver(channels);

    QuitProcess(channels);
    return 0;
}